home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / misc1 / iv26_w30.zip / SOURCES / CONTROL.C < prev    next >
C/C++ Source or Header  |  1992-03-03  |  5KB  |  236 lines

  1. /*
  2.  * Copyright (c) 1987, 1988, 1989 Stanford University
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Stanford not be used in advertising or
  9.  * publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  Stanford makes no representations about
  11.  * the suitability of this software for any purpose.  It is provided "as is"
  12.  * without express or implied warranty.
  13.  *
  14.  * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
  16.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  19.  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  20.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  21.  */
  22.  
  23. /*
  24.  * Implementation of control classes
  25.  */
  26.  
  27. #include <InterViews/control.h>
  28. #include <InterViews/message.h>
  29. #include <InterViews/sensor.h>
  30.  
  31. /** class Control **/
  32.  
  33. Control::Control(Interactor* i) { Init(nil, i); }
  34. Control::Control(const char* name, Interactor* i) { Init(name, i); }
  35.  
  36. void Control::Init(const char* name, Interactor* i) {
  37.     SetClassName("Control");
  38.     if (name != nil) {
  39.     SetInstance(name);
  40.     }
  41.     state = new ControlState;
  42.     state->Attach(this);
  43.     input = new Sensor;
  44.     input->Catch(EnterEvent);
  45.     input->Catch(LeaveEvent);
  46.     input->Catch(DownEvent);
  47.     input->Catch(UpEvent);
  48.     if (i != nil) {
  49.     Insert(i);
  50.     }
  51. }
  52.  
  53. Control::~Control () {
  54.     state->Detach(this);
  55. }
  56.  
  57. void Control::Handle(Event& e) {
  58.     switch (e.eventType) {
  59.     case DownEvent:
  60.     Down();
  61.     break;
  62.     case UpEvent:
  63.     Up();
  64.     break;
  65.     case EnterEvent:
  66.     Enter();
  67.     break;
  68.     case LeaveEvent:
  69.     Leave();
  70.     break;
  71.     }
  72. }
  73.  
  74. /*
  75.  * Hitting a control is equivalent to making the state active and
  76.  * then selecting it.
  77.  */
  78.  
  79. void Control::Down() {
  80.     if (!state->Active()) {
  81.     state->Activate();
  82.     state->NotifySelection(this);
  83.     }
  84. }
  85.  
  86. void Control::Enter() {
  87.     if (state->Active()) {
  88.     state->NotifySelection(this);
  89.     }
  90. }
  91.  
  92. void Control::Leave() {
  93.     if (state->Active()) {
  94.     state->NotifySelection(nil);
  95.     }
  96. }
  97.  
  98. void Control::Select() {
  99.     Highlight(true);
  100.     Open();
  101.     Grab();
  102. }
  103.  
  104. void Control::Unselect() {
  105.     Close();
  106.     Highlight(false);
  107. }
  108.  
  109. void Control::Grab() {
  110.     Event e;
  111.     do {
  112.     Read(e);
  113.     e.target->Handle(e);
  114.     if (e.target == this && e.eventType == LeaveEvent) {
  115.         Skip();
  116.         break;
  117.     }
  118.     } while (state != nil && state->Active());
  119. }
  120.  
  121. /*
  122.  * Skip all input events until we see something for another open control.
  123.  */
  124.  
  125. void Control::Skip() {
  126.     Event e;
  127.     for (;;) {
  128.     Read(e);
  129.     if (e.eventType == EnterEvent && IsGrabbing(e.target)) {
  130.         UnRead(e);
  131.         break;
  132.     } else if (e.eventType == UpEvent) {
  133.         Up();
  134.         break;
  135.     }
  136.     }
  137. }
  138.  
  139. /*
  140.  * Check whether an interactor (usually an event target) is a grabbing
  141.  * control.  Trivially, the current control is grabbing.  Any other controls
  142.  * attached to the control's state are also grabbing.  Similarly, any controls
  143.  * attached to other control's state up the stack from the current one
  144.  * are also considered to be grabbing.
  145.  */
  146.  
  147. boolean Control::IsGrabbing(Interactor* i) {
  148.     if (i == this) {
  149.     return true;
  150.     }
  151.     for (ControlState* c = state; c != nil; c = c->Next()) {
  152.     if (c->IsView(i)) {
  153.         return true;
  154.     }
  155.     }
  156.     for (c = state->Prev(); c != nil; c = c->Prev()) {
  157.     if (c->IsView(i)) {
  158.         return true;
  159.     }
  160.     }
  161.     return false;
  162. }
  163.  
  164. /*
  165.  * On an up event, deactivate all the control states and then
  166.  * call Do the current selection (if any).
  167.  */
  168.  
  169. void Control::Up() {
  170.     if (state->Active()) {
  171.     Control* target = state->Selection();
  172.     state->Action(target);
  173.     for (ControlState* c = state; c != nil; c = c->Prev()) {
  174.         c->Deactivate();
  175.     }
  176.     if (target != nil) {
  177.         target->Do();
  178.     }
  179.     }
  180. }
  181.  
  182. void Control::Open() { }
  183. void Control::Close() { }
  184. void Control::Do() { }
  185.  
  186. void Control::SetState(ControlState* s) {
  187.     state->Detach(this);
  188.     state = s;
  189.     s->Attach(this);
  190. }
  191.  
  192. /** class ControlState **/
  193.  
  194. ControlState::ControlState(unsigned s) {
  195.     status = s;
  196.     selection = nil;
  197.     action = nil;
  198.     next = nil;
  199.     prev = nil;
  200. }
  201.  
  202. ControlState::~ControlState() { }
  203.  
  204. void ControlState::NotifySelection(Control* c) {
  205.     if (selection != c) {
  206.     if (selection != nil) {
  207.         selection->Unselect();
  208.     }
  209.     selection = c;
  210.     if (selection != nil) {
  211.         selection->Select();
  212.     }
  213.     }
  214. }
  215.  
  216. void ControlState::Push(ControlState* s) {
  217.     next = s;
  218.     s->prev = this;
  219. }
  220.  
  221. void ControlState::Pop() {
  222.     if (prev != nil) {
  223.     prev->next = next;
  224.     prev = nil;
  225.     }
  226.     Deactivate();
  227. }
  228.  
  229. void ControlState::Deactivate() {
  230.     Set(ControlActive, false);
  231.     if (selection != nil) {
  232.     selection->Unselect();
  233.     selection = nil;
  234.     }
  235. }
  236.